/*! 
	\file nstilegrid.h
	
	\brief Header file for NSTileGrid class

	This file contains all of the neccessary declarations for the NSTileGrid class.

	\author Daniel Randle
	\date July 14 2013
	\copywrite Earth Banana Games 2013
*/

#ifndef NSTILEGRID_H
#define NSTILEGRID_H

#define X_GRID 0.86f
#define Y_GRID 1.49f
#define Z_GRID 0.45f
#define ROUND_FACTOR 0.5f
#define Z_GRIDSIZE 256
 //includes
#include <nsmath3d.h>
#include <nsobjectreference.h>
#include <vector>
#include <list>

/*! 
	NSTileGrid is the quick lookup container for all of the objects in the game.

	The class stores 8 quadrants with a 3 dimensional vector in each quadrant - every item in the game will be in one
	of these quadrants.

	The idea is that if you know the position of an object in 3D space you can quickly get the coordinates and quadrant
	do to the fact that everything is placed in the same grid system.

	So if you want to know the current position of the tile being moved you can call the getGridPos function
	inputing the 3D coords of the tile. You will get a struct containing the quadrant and the 3 int grid
	positions in the form of x, y, and z. This provides a very fast method of collision detection - simply check for
	collision with only the objects occupying the neighboring grid points.

	\bug No known bugs.
*/

class NSShader;
class NSMesh;

class NSTileGrid
{
	typedef std::list<NSObjectReference*> referenceList;
	typedef std::vector<referenceList> yGridSpace;
	typedef std::vector<yGridSpace> xGridSpace;
	typedef std::vector<xGridSpace>  Layers;

public:

	struct TilePosition
	{
		TilePosition(unsigned int z = 0, unsigned int x = 0, unsigned int y = 0):zIndex(z),xIndex(x),yIndex(y)
		{}

		std::string toString();
		unsigned int zIndex;
		unsigned int xIndex;
		unsigned int yIndex;
	};

	NSTileGrid(int size);
	~NSTileGrid();

	bool addReference(NSObjectReference* ref);
	bool addReference(NSObjectReference* ref, TilePosition indexPos);

	void drawOccupiedGridSpaces(const NSMatrix4Df & projCamMat);

	std::vector<TilePosition> getOccupiedTilePositions(NSObjectReference* ref);
	NSObjectReference * getReference(TilePosition pos);
	NSObjectReference * getReference(const NSVec3Df & worldPos);

	TilePosition getIndexFromPos(const NSVec3Df & pos);
	

	bool isOccupied(TilePosition pos);
	bool isOccupied(const NSVec3Df & worldPos);
	bool isVisible(NSObjectReference * ref);

	bool removeReference(NSObjectReference* ref);

	bool updateReference(NSObjectReference* ref);



private:
	int _xIndexEquation(float x, bool offset=false);
	int _yIndexEquation(float y);
	int _zIndexEquation(float z);
	TilePosition _getIndexFromDeviation(NSVec3Df & deviation);

	NSShader* occupiedShader;
	NSMesh * basicTile;
	Layers layers;
	std::list<TilePosition*> occupiedPositions;
	int mapSize;
};


#endif